/**
 * 应用调度类,负责根据应用的唯一标识符,返回应用对应的 内网IP 外网IP 域名 端口 负载情况
 * @author adv30 <adv30@126.com>
 * 2017年5月25日17:50:27
 */ 

const path = require('path')
const axios = require('axios')

const isArray = require('lodash/isArray')
const minBy = require('lodash/minBy')
const isObject = require('lodash/isObject')
const isNull = require('lodash/isNull')

const Base = require('../base/Base')
const serverAddress = require('../../config/server_address')
const ApiKey = require('../datawrapper/ApiKey')

const con = require('../../config/const')

axios.defaults.withCredentials = true
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

// 请求的解析 派发
class Dispatch extends Base
{
    // 对数据进行加工
    process (path, data, type = 'string') {
        // 将用户传入的如'serveruser/user/ApiUser/login'拆分成对象
        const pathObj = this._splitPath(path)
        // 需要判断是否拆分正确
        if (isNull(pathObj)) {
            return this.param_err(path, '访问路径拆分错误')
        }
        const addressObj = this._readAddress(pathObj.servername)
        if (!isObject(addressObj)) {
            // 要实现各种返回格式
            return this.param_err(path, '没有找到微服务的请求地址')
        }
        // 拼接地址
        const address = this._getAddress(addressObj)
        // 将数据进行包装 签名
        let send = ApiKey.wrapper(pathObj, data, type)
        return this.auto_success({address: address, send: send}, '对数据加工成功')
    }
    // 访问某个微服务 path:访问的路径 data:发送的数据 
    post (address, send) {
        return axios.post(address, send)
    }

    // 当所有请求都成功时才返回
    all (pathDatas, res) {
        const funArr = []
        const len = pathDatas.length

        for(let i = 0; i < len; i++){
            let processRes = this.process(pathDatas[i].path, pathDatas[i].param, 'obj')

            if (con.SUCCESS_STATUS === processRes.status) {
                try{
                    funArr.push(this.post(processRes.res.address, processRes.res.send))
                }catch(e){
                    res.json({e, message: '生成promise对象失败:' + e.message})
                }
            } else {
                funArr.push({})
            }
        }
//res.json({funArr})
        return axios.all(funArr)
    }

    // 将用户提供的path路径拆分
    _splitPath (path, flag = 'all', separator = '/') {
        let arr = path.split(separator)
        if (arr.length !== 4) {
            return null
        }
        let res = {
            servername: arr[0],
            ver: arr[0],
            module: arr[1],
            controller: arr[2],
            action: arr[3]
        }
        
        switch (flag.toLowerCase()) {
            case 'servername':
                res = res.servername
                break
            case 'ver':
                res = res.ver
                break
            case 'module':
                res = res.module
                break
            case 'controller':
                res = res.controller
                break
            case 'action':
                res = res.action
                break
            default:
                // all
        }
        return res
    }
    // 获取当前某个微服务最佳访问地址
    _getAddress (addressObj) {
       // 暂时先用内网地址去访问
       // return path.join(addressObj.networkIp, addressObj.path)
       // return path.join(addressObj.domainName, addressObj.path)
       // return addressObj.networkIp + '/' + addressObj.path
       return addressObj.domainName + '/' + addressObj.path
    }
    // 读取地址数据 
    _readAddress (serverName) {
        // 暂时先用读取配置的方式,将来会从某个配置微服务中读取 
        const addressArray = serverAddress[serverName]
        if (isArray(addressArray)) {
            return minBy(addressArray, o => {
                return o.load
            })
        }
        return null
    }

}

module.exports = new Dispatch()